import {intersectionWith, isEqual, mergeWith, unionWith, isArray, isObject } from 'lodash-es';

/**
 * Recursively merge two objects.
 * 递归合并两个对象。
 *
 * @param source The source object to merge from. 要合并的源对象。
 * @param target The target object to merge into. 目标对象，合并后结果存放于此。
 * @param mergeArrays How to merge arrays. Default is "replace".
 *        如何合并数组。默认为replace。
 *        - "union": Union the arrays. 对数组执行并集操作。
 *        - "intersection": Intersect the arrays. 对数组执行交集操作。
 *        - "concat": Concatenate the arrays. 连接数组。
 *        - "replace": Replace the source array with the target array. 用目标数组替换源数组。
 * @returns The merged object. 合并后的对象。
 */
export function deepMerge<T extends object | null | undefined, U extends object | null | undefined>(
    source: T,
    target: U,
    mergeArrays: 'union' | 'intersection' | 'concat' | 'replace' = 'replace',
): T & U {
    if (!target) {
        return source as T & U;
    }
    if (!source) {
        return target as T & U;
    }
    return mergeWith({}, source, target, (sourceValue: string | any, targetValue: any) => {
        if (isArray(targetValue) && isArray(sourceValue)) {
            switch (mergeArrays) {
                case 'union':
                    return unionWith(sourceValue, targetValue, isEqual);
                case 'intersection':
                    return intersectionWith(sourceValue, targetValue, isEqual);
                case 'concat':
                    return sourceValue.concat(targetValue);
                case 'replace':
                    return targetValue;
                default:
                    throw new Error(`Unknown merge array strategy: ${mergeArrays as string}`);
            }
        }
        if (isObject(targetValue) && isObject(sourceValue)) {
            return deepMerge(sourceValue, targetValue, mergeArrays);
        }
        return undefined;
    });
};

/**
 * 深拷贝函数，用于复制对象或数组的值，生成新的对象或数组
 * @param value 要被拷贝的值，可以是任何类型
 * @returns 返回深拷贝后的新值
 */
export const deepClone = (value: any) => {
    if(value === null || value === undefined || value === ''){
        return value;
    }
    const newValue = Array.isArray(value) ? [] : {}; //判断是不是数组，是数组就用[]，是对象就用{}；
    for (const key in value) {
        if( typeof value[key] !== 'object' ){
            newValue[key] = value[key];
        }else{
            newValue[key] = deepClone(value[key]);
        }
    }
    return newValue;
};

/**
 * 防抖函数
 */
export const debounce = (() => {
    let timer: string | number | NodeJS.Timeout | Fn | void | null | undefined = null;
    return (callback: () => void, wait = 800) => {
        timer && clearTimeout((timer as any));
        timer = setTimeout(callback, wait);
    };
})();

/**
 * 从给定的属性对象中获取动态属性，并返回 U 类型的部分属性对象
 *
 * @template T 给定属性对象的类型
 * @template U 返回的属性对象的类型
 * @param props 给定的属性对象
 * @returns 返回 U 类型的部分属性对象
 */
export function getDynamicProps<T extends Record<string, any>, U>(props: T): Partial<U> {
    const ret: Recordable = {};

    Object.keys(props).forEach((key) => {
        ret[key] = unref((props as Recordable)[key]);
    });

    return ret as Partial<U>;
}

/**
 * @description: 数字转换为中文数字
 * @param { number } num 需要转换的值
 **/
export const toChineseNumber = (num: number) => {
    const chineseNumbers = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
    const units = ['', '十', '百', '千', '万'];
    let str = '';
    if (num === 0) {
        return chineseNumbers[0];
    }
  
    const numStr = num.toString();
    for (let i = 0; i < numStr.length; i++) {
        str += chineseNumbers[numStr[i]] + units[numStr.length - i - 1];
    }
  
    return str.replace(/零[千百十]/g, '零').replace(/^零/, '');
};